경주로건설
NOTE
프로그래머스 Lv3 · BFS(방향 가중치 + 3차원 방문 배열) 단순 최단 거리가 아니라 진입 방향(코너)에 따라 비용이 달라지는 가중치 탐색. 2차원 방문 배열로는 코너 역전 현상을 놓치므로
[행][열][방향]3차원 방문 배열이 필요하다.
📝 문제
- 격자에서 출발점(0,0) → 도착점까지 경주로를 건설한다.
- 직선 도로 1칸 = 100원, 코너(방향 전환) = 500원. 최소 건설 비용을 구한다.
💡 접근
- 가중치가 방향에 따라 달라지므로 BFS(또는 우선순위 큐 다익스트라)가 DFS보다 압도적으로 유리하다.
- 상태에 ‘바라보는 방향’을 포함해야 한다:
Data(int row, int col, int direction, int cost). - 방문 기록을 **3차원
int[row][col][4]**로 두고 모두Integer.MAX_VALUE로 초기화 → 같은 칸이라도 도착 방향별로 최소 비용을 따로 관리. - 비용 갱신 조건: 새 비용이 기존 기록보다 **작거나 같을 때(
<=)**만 큐에 넣고 갱신. ‘같을 때’를 허용해야 다음 턴의 코너 역전을 노릴 수 있다.
📎 코너 비용이 600원인 이유 (500 + 100)
한 칸 이동한다는 것은 “다음 칸에 직선 도로(100원)를 새로 깐다”는 뜻이다.
- 직진(이전 방향과 같음): 직선 도로를 이어 붙이므로 +100원.
- 방향 전환(이전 방향과 다름): 직전 칸에 코너 블록(500원)을 설치하고, 꺾인 방향으로 한 칸 나아가려면 새 직선 도로(100원)도 깔아야 한다 → 500 + 100 = 600원이 한 번에 청구.
한 줄 요약: 자동차는 무조건 한 칸을 움직이므로 기본 이동 비용 100원은 깔고 가고, 핸들을 꺾었다면 코너 설치비 500원이 추가로 붙어 600원이 된다.
📎 오답 노트 (내가 놓쳤던 부분)
- DFS 백트래킹 상태 오염:
count = dfs(...)처럼 재귀 결과를 변수에 덮어써, 막힌 길에서 누적된 비용이 다른 길 탐색에 묻어가는 오류가 났다. (가중치 다른 최단거리 문제는 BFS가 유리.) - 비용 계산 오해: 방향이 꺾일 때 코너 비용(500)만 더했다. 실제로는 직진(100) + 코너(500) = 600을 더해야 한다.
- 코너 역전 현상(2차원 배열의 한계):
visited[][](2차원)로 비용을 기록하면, 600원(오른쪽 방향)으로 도착한 차가 500원(아래쪽 방향)짜리 때문에 탐색 종료당한다. 하지만 다음 목표가 ‘오른쪽’이면 600원 차는 직진(100)만, 500원 차는 코너(600)를 돌아야 해 최종적으로 600원 차가 더 싼 경우를 놓친다.
💡 복습 체크리스트 (다시 풀 때 설계)
- 3차원 배열 선언:
int[행][열][4] visited를 만들고 모두Integer.MAX_VALUE로 초기화. (마지막 차원 = 도착 시 바라보는 방향 0~3) - 상태 클래스: 큐에 넣을
Data(row, col, direction, cost). (첫 출발 예외: 초기 방향을 특수값으로 두어 첫 칸은 100원만 들도록) - 갱신 조건: 새 비용이 기존 기록보다 작거나 같을 때(
<=)만 큐에 넣고 갱신.
⏱️ 복잡도
- 시간:
O(N × N × 4)— 각 칸을 방향별(4)로 최대 한 번씩 처리. - 공간:
O(N × N × 4)— 3차원 방문 배열.
🔗 관련
- (Algorithm) 무인도여행 - 핵심 개념 및 특징 정리
- (Algorithm) 네트워크 - 핵심 개념 및 특징 정리
- (Algorithm) 단어변환 - 핵심 개념 및 특징 정리 — BFS/그래프 탐색 계열
- (BFS) 너비 우선 탐색 — BFS 개념 원류
- (Algorithm) 프로그래머스 260516 계획 - 핵심 개념 및 특징 정리 — Phase 1 완전 탐색 고급 문제로 참조